// 核心思想
// 条款15的核心思想是：资源管理类需要提供一种方式来访问它所管理的原始资源，因为很多API仍然需要直接使用原始资源（如裸指针、句柄等）。

// 详细解析
// 1. 为什么需要访问原始资源？
// 当我们使用RAII类（如智能指针）管理资源时，可能会遇到需要使用原始资源的情况：
// 假设我们有一个使用RAII管理的字体资源
// 如果Font类没有提供访问FontHandle的方法，我们就无法使用changeFontSize函数。
class Font
{
private:
    FontHandle h; // 原始字体句柄

public:
    explicit Font(FontHandle handle) : h(handle) {}
    ~Font() { releaseFont(h); } // 自动释放资源
};

// 问题：如何将Font对象传递给需要FontHandle的API？
void changeFontSize(FontHandle f, int newSize); // 第三方API，需要原始句柄

// 2. 提供原始资源访问的方法
// 方法1：显式转换函数
// 优点：使用简洁 缺点：可能导致意外的隐式转换，增加出错风险
class Font
{
private:
    FontHandle h;

public:
    explicit Font(FontHandle handle) : h(handle) {}
    ~Font() { releaseFont(h); }

    // 显式转换函数
    // 不是返回一个名为"operator"的类型，
    // 而是定义了一个类型转换运算符。这是C++中的一种特殊成员函数，允许将对象隐式或显式地转换为其他类型。
    operator FontHandle() const { return h; }
    // 类型转换运算符详解
    // 类型转换运算符的语法是：operator TargetType() const;
};

// 使用方式
Font f(getFont());
changeFontSize(f, 12); // 隐式转换为FontHandle

// 方法2：显式访问方法
// 优点：明确表达意图，避免意外转换 缺点：使用稍微繁琐
class Font
{
private:
    FontHandle h;

public:
    explicit Font(FontHandle handle) : h(handle) {}
    ~Font() { releaseFont(h); }

    // 显式访问方法
    FontHandle get() const { return h; }
};

// 使用方式
Font f(getFont());
changeFontSize(f.get(), 12); // 显式获取原始资源

// 3. 标准库中的实践
// C++标准库中的智能指针都提供了访问原始指针的方法：
std::shared_ptr<Investment> pInv(createInvestment());

// 使用get()方法获取原始指针
Investment *rawPtr = pInv.get();
someFunction(rawPtr);

// unique_ptr也提供get()方法
std::unique_ptr<Widget> pWidget(new Widget);
processWidget(pWidget.get());

// 4. 安全性考虑
// 提供原始资源访问时，需要注意以下安全问题：
// 资源所有权混淆
std::shared_ptr<Investment> pInv(createInvestment());
Investment *rawPtr = pInv.get();

delete rawPtr; // 灾难！资源被提前释放
// 当pInv销毁时，会再次尝试释放已经被删除的资源
// 悬空引用
Investment *rawPtr;
{
    std::shared_ptr<Investment> pInv(createInvestment());
    rawPtr = pInv.get(); // 获取原始指针
} // pInv销毁，资源被释放

useInvestment(rawPtr); // 灾难！使用已释放的资源

// 5. 设计建议
// 根据资源特性和使用场景，选择合适的访问方式：

// 对于可能被误用的资源
class Font
{
private:
    FontHandle h;

public:
    // ...

    // 只提供显式访问方法，不提供隐式转换
    FontHandle get() const { return h; }
};

// 对于常用且安全的资源
template <typename T>
class MySharedPtr
{
private:
    T *ptr;
    // 引用计数等其他成员...

public:
    // ...

    // 提供多种访问方式
    T *get() const { return ptr; }        // 显式方法
    operator T *() const { return ptr; }  // 隐式转换（谨慎使用）
    T &operator*() const { return *ptr; } // 解引用操作符
    T *operator->() const { return ptr; } // 箭头操作符
};

// 6. 实际应用示例
// 文件句柄管理
class FileWrapper
{
private:
    FILE *file;

public:
    explicit FileWrapper(const char *filename)
        : file(fopen(filename, "r"))
    {
        if (!file)
            throw std::runtime_error("Failed to open file");
    }

    ~FileWrapper()
    {
        if (file)
            fclose(file);
    }

    // 禁止复制
    FileWrapper(const FileWrapper &) = delete;
    FileWrapper &operator=(const FileWrapper &) = delete;

    // 提供原始资源访问
    FILE *get() const { return file; }

    // 提供便捷方法
    size_t read(void *buffer, size_t size, size_t count)
    {
        return fread(buffer, size, count, file);
    }
};

// 使用方式
void processFile()
{
    FileWrapper f("data.txt");

    // 直接使用包装方法
    char buffer[100];
    f.read(buffer, 1, 100);

    // 需要原始句柄时
    long fileSize;
    fseek(f.get(), 0, SEEK_END);
    fileSize = ftell(f.get());
}